package com.yp.infrastructure.shiro.configuration;


import com.yp.infrastructure.shiro.model.CustomRealm;
import com.yp.infrastructure.shiro.service.ISecurityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Lazy
@Configuration
public class ShiroConfiguration implements BeanPostProcessor {


    private final static String FILTER_NAME = "jwt";

    private final ISecurityService securityService;

    private final CustomRealm customRealm;


    @Lazy
    public ShiroConfiguration(ISecurityService securityService,
                              CustomRealm customRealm) {
        this.securityService = securityService;
        this.customRealm = customRealm;
    }

    @Bean
    public DefaultWebSecurityManager webSecurityManager() {
        log.debug("create security manager.");
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(customRealm);
        return securityManager;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Lazy @Autowired DefaultWebSecurityManager webSecurityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(webSecurityManager);
        return advisor;
    }


    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Lazy @Autowired WebSecurityManager webSecurityManager) {
        log.debug("configure url rules.");
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put(FILTER_NAME, new AuthenticationFilter(securityService));
        factoryBean.setFilters(filterMap);
        factoryBean.setSecurityManager(webSecurityManager);

        Map<String, String> filterRuleMap = new HashMap<>();
        setExcludeUrls(filterRuleMap, securityService.urls());
        setSwaggerUrls(filterRuleMap);
        setDefaultUrls(filterRuleMap);
        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }


    private void setExcludeUrls(Map<String, String> map, List<String> list) {
        list.forEach(x -> map.put(x, "anon"));
    }


    private void setDefaultUrls(Map<String, String> map) {
        map.put("/favicon.ico", "anon");
        map.put("/index", "anon");
        map.put("/index.html", "anon");
        map.put("/index.jsp", "anon");
        map.put("/**", FILTER_NAME);
    }

    private void setSwaggerUrls(Map<String, String> map) {
        map.put("/swagger/**", "anon");
        map.put("/swagger-ui/**", "anon");
        map.put("/v3/**", "anon");
        map.put("/webjars/**", "anon");
    }


}
